#include "fenetre.h"
#include "ui_fenetre.h"
#include "configgame.h"

Fenetre::Fenetre(Client* c, MyThread* mt, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Fenetre),
    _mythread(mt),
    _client(c),
    map(NULL),
    camps(NULL)
{
    ui->setupUi(this);

    QString etat(_mythread->getMessage().c_str());
    newMsg(etat); // Pour savoir si connecte ou deconnecte

    scrAct = eDEF;
    defScreen = new DefaultScreen(this, ui->wEmp1);
    defScreen->show();

    QObject::connect(ui->bCreer, SIGNAL(clicked()), this, SLOT(createGame()));
    QObject::connect(ui->bQuitter, SIGNAL(clicked()), this, SLOT(quitter()));
    QObject::connect(ui->lineChat, SIGNAL(returnPressed()), this, SLOT(lineChatReturn()));

    QObject::connect(_mythread, SIGNAL(newClient(QString)), this, SLOT(newClient(QString)));
    QObject::connect(_mythread, SIGNAL(newGame(QString, int, int)), this, SLOT(newGame(QString, int, int)));
    QObject::connect(_mythread, SIGNAL(newMsg(QString)), this, SLOT(newMsg(QString)));
    QObject::connect(_mythread, SIGNAL(decoC(QString)), this, SLOT(decoClient(QString)));
    QObject::connect(_mythread, SIGNAL(decoP(QString)), this, SLOT(decoGame(QString)));
    QObject::connect(_mythread, SIGNAL(joinGame(int)), this, SLOT(traitementJoinGame(int)));
    QObject::connect(_mythread, SIGNAL(createGame(int)), this, SLOT(traitementCreateGame(int)));
    QObject::connect(_mythread, SIGNAL(addPartie(QString)), this, SLOT(slotAddPartie(QString)));
    QObject::connect(_mythread, SIGNAL(rmPartie(QString)), this, SLOT(slotRmPartie(QString)));
    QObject::connect(_mythread, SIGNAL(datasGame(int,int)), this, SLOT(slotDatasGame(int,int)));
    QObject::connect(_mythread, SIGNAL(addPoint(int, int)), this, SLOT(slotAddPoint(int, int)));
    QObject::connect(_mythread, SIGNAL(idJoueur(int)), this, SLOT(slotIdJoueur(int)));
    QObject::connect(_mythread, SIGNAL(launch()), this, SLOT(slotLaunch()));
    QObject::connect(_mythread, SIGNAL(newClientSalon(QString)), this, SLOT(addClientSalon(QString)));
    QObject::connect(_mythread, SIGNAL(delClientSalon(QString)), this, SLOT(rmClientSalon(QString)));
    QObject::connect(_mythread, SIGNAL(salQuit()), this, SLOT(slotSalQuit()));
    QObject::connect(_mythread, SIGNAL(changeEtat(int)), this, SLOT(traitementChangeEtat(int)));
    QObject::connect(_mythread, SIGNAL(selectionT(int, int)), this, SLOT(traitementSelectionT(int, int)));
    QObject::connect(_mythread, SIGNAL(tmaj(int,int,int,int)), this, SLOT(traitementTMaj(int,int,int,int)));
    QObject::connect(_mythread, SIGNAL(win(QString)), this, SLOT(traitementWin(QString)));

    sf::Packet p;

    p << eMAIN_ALLCLIENTS;
    _client->send(p, true);
    p.clear();

    p << eMAIN_ALLGAMES;
    _client->send(p, true);
}

Fenetre::~Fenetre()
{
    delete ui;
}

void Fenetre::addText(QString q)
{
    ui->textChat->append(q);
}

void Fenetre::addClient(QString q)
{
    ui->textClients->append(q);
}

void Fenetre::addPartie(QString q)
{
    ui->textParties->append(q);
}

void Fenetre::refreshClients()
{
    ui->textClients->clear();
    for (std::list<MyClient>::iterator i = clients.begin(); i != clients.end(); ++i)
    {
        this->addClient(QString(i->nom.c_str()));
    }
}

void Fenetre::refreshGames()
{
    ui->textParties->clear();

    if (scrAct == eDEF)
    {
        defScreen->clearPartie();
    }

    for (std::list<MyGame>::iterator i = games.begin(); i != games.end(); ++i)
    {
        std::ostringstream os1, os2;
        os1 << (int)i->nbJoueursAct;
        os2 << (int)i->nbJoueursMax;
        std::string ligne = os1.str() + "/" + os2.str() + " " + i->nom;
        this->addPartie(QString(ligne.c_str()));

        if (scrAct == eDEF)
        {
            this->defScreen->addPartie(QString(ligne.c_str()));
        }
    }
}

void Fenetre::deleteScreenAct()
{
    switch (scrAct)
    {
        case eDEF :
            delete defScreen;
            break;
        case eCFG :
            delete cfgGame;
            break;
        case eSAL :
            delete salScreen;
            break;
        case eCANV :
            delete canvasSfml;
            break;
    }
}

void Fenetre::quitter()
{
    sf::Packet p;
    p << eMAIN_DECOCLIENT;
    _client->send(p, true);

    if (scrAct == eCANV)
    {
        _client->send(p, false);
    }

    if (scrAct == eSAL)
    {
        p.clear();
        p << eMAIN_DELCLSALON;
        _client->send(p, true);
    }

    _mythread->quitter();
    qApp->quit();
}

void Fenetre::lineChatReturn()
{
    sf::Packet p;
    p << eMAIN_NEWMSG;

    _client->send(p, true);

    std::string msg;
    msg = "[" + _client->_pseudo.toStdString() + "] >> " + ui->lineChat->text().toStdString();

    p.clear();
    p << msg;

    _client->send(p, true);
    ui->lineChat->setText("");
}

void Fenetre::newClient(QString n)
{
    MyClient mc;
    mc.nom = n.toStdString();
    clients.push_back(mc);
    this->addClient(n);
}

void Fenetre::newGame(QString n, int ja, int jm)
{
    MyGame mg;
    mg.nom = n.toStdString();
    mg.nbJoueursAct = (sf::Uint8)ja;
    mg.nbJoueursMax = (sf::Uint8)jm;
    games.push_back(mg);

    std::ostringstream os1, os2;
    os1 << (int)mg.nbJoueursAct;
    os2 << (int)mg.nbJoueursMax;
    std::string ligne = os1.str() + "/" + os2.str() + " " + mg.nom;
    this->addPartie(QString(ligne.c_str()));

    if (scrAct == eDEF)
    {
        defScreen->addPartie(QString(ligne.c_str()));
    }
}

void Fenetre::newMsg(QString m)
{
    this->addText(m);
}

void Fenetre::decoClient(QString c)
{
    for (std::list<MyClient>::iterator i = clients.begin(); i != clients.end(); ++i)
    {
        if(i->nom == c.toStdString())
        {
            clients.erase(i);
            i = clients.end();
        }
    }
    refreshClients();
}

void Fenetre::decoGame(QString g)
{
    for (std::list<MyGame>::iterator i = games.begin(); i != games.end(); ++i)
    {
        if(i->nom == g.toStdString())
        {
            games.erase(i);
            i = games.end();
        }
    }
    refreshGames();
}

void Fenetre::joinGame()
{
    if (defScreen->isServerSelected())
    {
        sf::Packet p;
        p << eJOIN_GAME;

        _client->send(p, true);

        p.clear();
        int j(0);

        for (std::list<MyGame>::iterator i = games.begin(); i != games.end(); ++i)
        {
            if(j == defScreen->getCurrentRow())
            {
                p << i->nom;
            }
            j++;
        }

        _client->send(p, true);
    }
    else
    {
        QMessageBox::critical(NULL, "Erreur", "Aucun serveur selectionne");
    }

}

void Fenetre::traitementJoinGame(int x)
{
    switch (x)
    {
        case 0 :
        {
            QMessageBox::critical(NULL, "Erreur", "La partie n'existe pas");
        } break;

        case 1 :
        {
            clientsSalon.clear();
            centres.clear();

            int j(0);
            std::string nom;

            for (std::list<MyGame>::iterator i = games.begin(); i != games.end(); ++i)
            {
                if(j == defScreen->getCurrentRow())
                {
                    nom = i->nom;
                }
                j++;
            }

            deleteScreenAct();

            ui->bCreer->setEnabled(false);
            scrAct = eSAL;
            salScreen = new salonScreen(this, ui->wEmp1);
            salScreen->setNomPartie(QString(nom.c_str()));

            salScreen->show();
        } break;

        case 2 :
        {
            QMessageBox::critical(NULL, "Erreur", "Partie pleine");
        } break;

        default :
            if (DEBUG) {std::cout << "erreur switch join game" << std::endl;}
            break;
    }
}

void Fenetre::slotRetourMenu()
{
    deleteScreenAct();

    ui->bCreer->setEnabled(true);
    scrAct = eDEF;
    defScreen = new DefaultScreen(this, ui->wEmp1);
    defScreen->show();
}

void Fenetre::createGame()
{
    deleteScreenAct();

    ui->bCreer->setEnabled(false);
    scrAct = eCFG;
    cfgGame = new ConfigGame(this, ui->wEmp1);
    cfgGame->show();
}

void Fenetre::sendNewGame()
{
    QString nom = cfgGame->getNomPartie();
    sf::Uint8 nbJ = cfgGame->getNbJoueurs();
    std::string nomP = nom.toStdString();
    if(! nom.isEmpty())
    {
        sf::Packet p;
        p << eNEW_GAME;
        _client->send(p, true);

        p.clear();

        p << nomP << nbJ;
        _client->send(p, true);
    }

    else
    {
        QMessageBox::critical(NULL, "Erreur", "Le nom de la partie est vide");
    }
}

void Fenetre::traitementCreateGame(int x)
{
    if (x == 1)
    {
        clientsSalon.clear();
        centres.clear();

        QString nom = cfgGame->getNomPartie();

        deleteScreenAct();

        ui->bCreer->setEnabled(false);
        scrAct = eSAL;
        salScreen = new salonScreen(this, ui->wEmp1);
        salScreen->setNomPartie(nom);

        salScreen->show();
    }
    else if (x == 0)
    {
        QMessageBox::critical(NULL, "Erreur", "La partie existe deja");
    }
}

void Fenetre::slotAddPartie(QString n)
{
    for (std::list<MyGame>::iterator i = games.begin(); i != games.end(); ++i)
    {
        if(i->nom == n.toStdString())
        {
            i->nbJoueursAct++;
        }
    }
    refreshGames();
}

void Fenetre::slotRmPartie(QString n)
{
    for (std::list<MyGame>::iterator i = games.begin(); i != games.end(); ++i)
    {
        if(i->nom == n.toStdString())
        {
            i->nbJoueursAct--;
        }
    }
    refreshGames();
}

void Fenetre::slotReady()
{
    sf::Packet p;
    p << eMAIN_READY;
    _client->send(p, true);
}

void Fenetre::slotDatasGame(int dnbJ, int dnbTparJ)
{
    nbJ = dnbJ;
    nbTparJ = dnbTparJ;
}

void Fenetre::slotAddPoint(int x, int y)
{
    centres.push_back(std::pair<int, int>(x, y));
}

void Fenetre::slotIdJoueur(int x)
{
    idJoueur = x;
    std::string clrStr = "--- Votre couleur ---";

    switch (x)
    {
        case 0 :
            clrStr = "<font color=\"#780000\">" + clrStr + "</font>";
            break;

        case 1 :
            clrStr = "<font color=\"#121B94\">" + clrStr + "</font>";
            break;

        case 2 :
            clrStr = "<font color=\"#007800\">" + clrStr + "</font>";
            break;

        case 3 :
            clrStr = "<font color=\"#EE6E0D\">" + clrStr + "</font>";
            break;

        case 4 :
            clrStr = "<font color=\"#4F0C78\">" + clrStr + "</font>";
            break;

        case 5 :
            clrStr = "<font color=\"#E6B414\">" + clrStr + "</font>";
            break;

        case 6 :
            clrStr = "<font color=\"#46D2BE\">" + clrStr + "</font>";
            break;

        case 7 :
            clrStr = "<font color=\"#FA78B4\">" + clrStr + "</font>";
            break;

        default :
            clrStr = "Mauvais ID Joueur";
            break;
    }

    QString clrQstr(clrStr.c_str());
    newMsg(clrQstr); // Pour savoir sa couleur
}

void Fenetre::slotLaunch()
{
    if(map) {delete map;}
    map = new Carte();

    map->setTab(nbJ * nbTparJ);

    for (int i(0); i < nbJ * nbTparJ; i++)
    {
        map->setCentre(i, sf::Vector2i(centres.at(i).first, centres.at(i).second));
    }

    map->genererCarteClient(nbJ, nbTparJ);

    if(camps) {delete camps;}
    camps = new Camp[nbJ];

    for (int i(0); i < nbJ; i++)
    {
        camps[i].setIndice(i);
    }

    map->repartirTerritoires(nbJ, nbTparJ, camps);

    deleteScreenAct();

    ui->bCreer->setEnabled(false);

    scrAct = eCANV;
    canvasSfml = new MyCanvas(ui->wEmp1, QPoint(0, 0), QSize(801, 591), map, camps, idJoueur, &etat, _client);
    canvasSfml->show();
}

void Fenetre::addClientSalon(QString n)
{
    MyClient mc;
    mc.nom = n.toStdString();
    clientsSalon.push_back(mc);

    if (scrAct == eSAL)
    {
       salScreen->addClient(QString(mc.nom.c_str()));
    }
}

void Fenetre::rmClientSalon(QString n)
{
    for (std::list<MyClient>::iterator i = clientsSalon.begin(); i != clientsSalon.end(); ++i)
    {
        if(i->nom == n.toStdString())
        {
            clientsSalon.erase(i);
            i = clientsSalon.end();
        }
    }

    if(scrAct == eSAL)
    {
        salScreen->clearClients();
        for (std::list<MyClient>::iterator i = clientsSalon.begin(); i != clientsSalon.end(); ++i)
        {
            salScreen->addClient(QString(i->nom.c_str()));
        }
    }
}

void Fenetre::slotQuitSalon()
{
    sf::Packet p;
    p << eMAIN_DELCLSALON;
    _client->send(p, true);

    deleteScreenAct();

    ui->bCreer->setEnabled(true);
    scrAct = eDEF;
    defScreen = new DefaultScreen(this, ui->wEmp1);
    defScreen->show();
}

void Fenetre::slotSalQuit()
{
    QMessageBox::critical(NULL, "Erreur", "Serveur deconnecte. Fermeture du programme.");

    qApp->quit();
}

void Fenetre::traitementChangeEtat(int x)
{
    etat = x;
}

void Fenetre::traitementSelectionT(int x, int y)
{
    canvasSfml->setIdSelection(x, y);
}

void Fenetre::traitementTMaj(int numT, int nbDes, int numC, int debut)
{
    map->territoires[numT]->setNbDesCourant(nbDes);
    map->territoires[numT]->setIndiceCamp(numC);

    if (debut == 1)
    { map->updateTexture(canvasSfml->getS(), canvasSfml->getD()); }

    canvasSfml->setIdSelection(-1, -1);
}

void Fenetre::traitementWin(QString qs)
{
    std::string msg = "<strong>" + qs.toStdString() + "</strong> remporte la partie !";
    QMessageBox::information(this, "Vainqueur !", msg.c_str());

    deleteScreenAct();

    ui->bCreer->setEnabled(true);
    scrAct = eDEF;
    defScreen = new DefaultScreen(this, ui->wEmp1);
    defScreen->show();
}

void Fenetre::closeEvent(QCloseEvent *event)
{
    this->quitter();
}

